
14.10.2017, 17:32
|
Новичок на форуме
|
|
Регистрация: 14.10.2017
Сообщений: 5
|
|
Ajax корзина на сайте. Помощь.
Добрый день! Подскажите как реализовать корзину на сайте методом ajax. Я не силён в js поэтому если можно объясните как новичку. Я не понимаю как средствами ajax добавить товар в массив $_SESSION['cart']? Да и вообще как должна правильно работать ajax корзина? Я хочу что бы при нажатии на ссылку "добавить в корзину" всплывал alert с текстом "Товар успешно добавлен в корзину" и соответственно сам товар добавлялся в массив $_SESSION['cart'].
Заранее большое спасибо!
На данный момент у меня так:
HTML:
Так выводятся товары:
<div class="goods">
<a href="?view=product&goods_id=<?=$product['goods_id']?>"><img width="200" height="200" src="<?=PRODUCTIMG?><?=$product['img']?>" alt="Картинка товара" /></a>
<a class="good_name" href="?view=product&goods_id=<?=$product['goods_id']?>"><?=$product['name']?></a>
<p class="price">Цена: <span><?=$product['price']?> р.</span></p>
<a href="?view=addtocart&goods_id=<?=$product['goods_id']?>"><img class="addtocart" src="<?=TEMPLATE?>images/addcart.png" alt="Добавить в корзину" /></a>
</div><!-- .goods -->
Такой блок корзины:
<div class="basket">
<?php if($_SESSION['total_quantity']): ?>
<a href="?view=cart"><img src="<?=TEMPLATE?>images/cart.png" alt="Корзина" /></a>
<h4>Товаров в <a href="?view=cart">Вашей корзине:</a><br /> <span><?=$_SESSION['total_quantity']?></span> на сумму <span><?=$_SESSION['total_sum']?></span> руб.</h4>
<?php else: ?>
<a href="?view=cart"><img src="<?=TEMPLATE?>images/cart.png" alt="Корзина" /></a>
<h4>Товаров в <a href="?view=cart">Вашей корзине:</a> <span>0</span></h4>
<?php endif; ?>
</div>
При клике на ссылку "добавить в корзину" срабатывают функции:
PHP
addtocart:
function addtocart($goods_id, $qty = 1){
if(isset($_SESSION['cart'][$goods_id])){
// если в массиве cart уже есть добавляемый товар
$_SESSION['cart'][$goods_id]['qty'] += $qty;
return $_SESSION['cart'];
}else{
// если товар кладется в корзину впервые
$_SESSION['cart'][$goods_id]['qty'] = $qty;
return $_SESSION['cart'];
}
}
total_sum:
function total_sum($goods){
$total_sum = 0;
$query = "SELECT goods_id, name, price, img
FROM goods
WHERE goods_id IN (" .implode(',',array_keys($goods)). ")";
$res = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_assoc($res)){
$_SESSION['cart'][$row['goods_id']]['name'] = $row['name'];
$_SESSION['cart'][$row['goods_id']]['price'] = $row['price'];
$_SESSION['cart'][$row['goods_id']]['img'] = $row['img'];
$total_sum += $_SESSION['cart'][$row['goods_id']]['qty'] * $row['price'];
}
return $total_sum;
}
total_quantity
function total_quantity(){
$_SESSION['total_quantity'] = 0;
foreach($_SESSION['cart'] as $key => $value){
if(isset($value['price'])){
// если получена цена товара из БД - суммируем кол-во
$_SESSION['total_quantity'] += $value['qty'];
}else{
// иначе - удаляем такой ID из сессиии (корзины)
unset($_SESSION['cart'][$key]);
}
}
}
|
|

14.10.2017, 17:54
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
MikhailM1993,
корзина должна хранить не только количество товара, но и его цену, иначе при каждом обращении к корзине вы третируете базу запросами, так как добавление/изменение/удаление в корзине требует перерасчета.
Ajax всего лишь метод обмена с сервером, а все работать будет точно также.
|
|

14.10.2017, 20:50
|
Новичок на форуме
|
|
Регистрация: 14.10.2017
Сообщений: 5
|
|
Сообщение от laimas
|
MikhailM1993,
корзина должна хранить не только количество товара, но и его цену, иначе при каждом обращении к корзине вы третируете базу запросами, так как добавление/изменение/удаление в корзине требует перерасчета.
Ajax всего лишь метод обмена с сервером, а все работать будет точно также.
|
laimas, Вы можете подсказать как это реализовать? я не понимаю...
мне же для начала нужно запретить стандартное поведение ссылки, далее создать переменные goods_id, price и qty (у меня количество товара всегда равно 1). Т.е. код будет выглядить так:
в HTML в строке: "<a href="?view=addtocart&goods_id=<?=$product['goods_id']?>"><img class="addtocart" src="<?=TEMPLATE?>images/addcart.png" alt="Добавить в корзину" /></a>"
я добавляю ссылке класс class="addtocart", id="<?=$product['price']?>" и атрибут rel="<?=$product['goods_id']?>"
далее в файле с скриптами пишу такую функцию:
$(".addtocart").click(functions(e){
e.preventDefault(); // этим отменяю стандартное поведение ссылки
var good_id = $(this).attr("rel"); // здесь получаю id товара
var price = $(this).attr("id");// здесь получаю цену товара
var qty = 1;
// и вот после того как я получил значения в переменные, я не понимаю что делать....
$.ajax({
url: './', // обрабатываю я же всё здесь же в индексном файле
type: 'POST',
data: {good_id: good_id, price: price, qty: qty},
success:function{
},
error:function(){
}
});
Вот что мне писать в блока success и error? Помогите пожалуйста я не понимаю.
|
|

14.10.2017, 21:02
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Сообщение от MikhailM1993
|
далее создать переменные goods_id, price и qty (у меня количество товара всегда равно 1).
|
Зачем? И если всегда по 1, то зачем же
// если в массиве cart уже есть добавляемый товар
$_SESSION['cart'][$goods_id]['qty'] += $qty;
может быть пусть и выбирает сколько ему надо, а не щелкать по одному много раз, ну это же неудобно.
И форматируйте свой код, ну невозможно его читать. Отформатируете, тогда можно и говорить, просмотрев что у вас есть.
|
|

16.10.2017, 16:30
|
Новичок на форуме
|
|
Регистрация: 14.10.2017
Сообщений: 5
|
|
laimas, по поводу количества, можно конечно сделать инпут где и вводить количество, но мой шаблон этого не подразумевает...
На данный момент у меня так:
Вот такая у меня корзина:
<div class="basket">
<?php if($_SESSION['total_quantity']): ?>
<a href="?view=cart"><img src="<?=TEMPLATE?>images/cart.png" alt="Корзина" /></a>
<h4>Товаров в <a href="?view=cart">Вашей корзине:</a><br />
<span><?=$_SESSION['total_quantity']?></span> на сумму <span><?=$_SESSION['total_sum']?></span> руб.</h4>
<?php else: ?>
<a href="?view=cart"><img src="<?=TEMPLATE?>images/cart.png" alt="Корзина" /></a>
<h4>Товаров в <a href="?view=cart">Вашей корзине:</a> <span>0</span></h4>
<?php endif; ?>
</div>
Вот так выводятся товары на странице:
<div class="goods">
<a href="?view=product&goods_id=<?=$product['goods_id']?>"><img width="200" height="200" src="<?=PRODUCTIMG?><?=$product['img']?>" alt="Картинка товара" /></a>
<a class="good_name" href="?view=product&goods_id=<?=$product['goods_id']?>"><?=$product['name']?></a>
<p class="price">Цена: <span><?=$product['price']?> р.</span></p>
<a rel="<?=$product['goods_id']?>" id="<?=$product['price']?>" href="?view=addtocart&goods_id=<?=$product['goods_id']?>"><img class="addtocart" src="<?=TEMPLATE?>images/addcart.png" alt="Добавить в корзину" /></a>
</div>
Далее при клике на ссылку добавить в корзину вызываются функции:
addtocart:
function addtocart($goods_id, $qty = 1){
if(isset($_SESSION['cart'][$goods_id])){
// если в массиве cart уже есть добавляемый товар
$_SESSION['cart'][$goods_id]['qty'] += $qty;
return $_SESSION['cart'];
}else{
// если товар кладется в корзину впервые
$_SESSION['cart'][$goods_id]['qty'] = $qty;
return $_SESSION['cart'];
}
}
total_sum:
function total_sum($goods){
$total_sum = 0;
$query = "SELECT goods_id, name, price, img
FROM goods
WHERE goods_id IN (" .implode(',',array_keys($goods)). ")";
$res = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_assoc($res)){
$_SESSION['cart'][$row['goods_id']]['name'] = $row['name'];
$_SESSION['cart'][$row['goods_id']]['price'] = $row['price'];
$_SESSION['cart'][$row['goods_id']]['img'] = $row['img'];
$total_sum += $_SESSION['cart'][$row['goods_id']]['qty'] * $row['price'];
}
return $total_sum;
}
total_quantity:
function total_quantity(){
$_SESSION['total_quantity'] = 0;
foreach($_SESSION['cart'] as $key => $value){
if(isset($value['price'])){
// если получена цена товара из БД - суммируем кол-во
$_SESSION['total_quantity'] += $value['qty'];
}else{
// иначе - удаляем такой ID из сессиии (корзины)
unset($_SESSION['cart'][$key]);
}
}
}
Ну и далее как я и писал я не понимаю что делать что бы заставить данные передаваться AJAX-ом, вот мой набросок скрипта... возможно в корне не правильный но всё же...
$(".addtocart").click(functions(e){
e.preventDefault(); // этим отменяю стандартное поведение ссылки
// далее как я понимаю, мне нужно создать переменные и положить в них данные товара, например вот так.
var good_id = $(this).attr("rel"); // здесь получаю id товара
var price = $(this).attr("id");// здесь получаю цену товара
var qty = 1;
// и вот после того как я получил значения в переменные, я не понимаю что делать....
$.ajax({
url: './', // обрабатываю я же всё здесь же в индексном файле
type: 'POST',
data: {good_id: good_id, price: price, qty: qty},
success:function{
},
error:function(){
}
};
});
P.S. Прошу прощения за долгий ответ, не было возможности ответить раньше.
|
|

17.10.2017, 10:26
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Сначала по самой корзине. Вот что у вас происходит - total_sum($goods), и это постоянно ибо требуется всегда. А выгоднее не дергать БД постоянно, помещая в корзину минимум нужной информации о товаре. Для этого достаточно иметь структуру товаров в корзине как показано и получение всего товаров в корзине, и их сумма, это просто описать готовыми функциями:
$cart = [
345 => [
'count' => 4,
'price' => 150,
'props' => ['name' => 'Печеньки', 'brand' => 'ООО Тесто']
],
224 => [
'count' => 3,
'price' => 250,
'props' => ['name' => 'Семечки', 'brand' => 'АО Щелкай!']
]
];
//количество товаров в корзине
$count = array_sum(array_map('current', $cart));
//или с версии 5.5.0 можно так
$count = array_sum(array_column($cart, 'count'));
//сумма набранного
$total = array_sum(array_map('array_product', $cart));
Писать для этого такие функции как total_sum() и total_quantity() стоит ли?
Названия товаров и прочие параметры хранятся в массиве, значение которого функция array_product, при расчете суммы, возвращает равное 1, а значит не влияет на расчет.
При добавлении товаров в корзину из базы получается цена, название товара, и прочее необходимое. Корзина имеет два представления, но обслуживается одними и теми же данными, а значит для полного представления ее выгоднее иметь информацию уже в ней. То есть обращения к БД сводятся только к одноразовым запросам при добавлении нового товара в корзину.
Если товар добавляется только по одному, непонятен вообще второй аргумент функции addtocart(). И это связано с клиентской реализацией - как HTML структурой, так и функционалом. Обычно в таком случае, это кнопка "Добавить в корзину", серверу отправляется ID выбранного товара, он либо добавляется, либо икремент ранее добавленного. На клиенте при этом у товара будет информация типа "В корзине N штук".
Каким образом у вас клиентская часть организована (покажите результирующий html-код, а не шаблон на сервере с РНР вставками)?
Последний раз редактировалось laimas, 17.10.2017 в 10:35.
|
|

18.10.2017, 10:55
|
Новичок на форуме
|
|
Регистрация: 14.10.2017
Сообщений: 5
|
|
laimas,
Вот так выводиться товар:
<div class="goods">
<a href="?view=product&goods_id=48"><img src="baseimg/48.jpg" alt="Картинка товара" width="200" height="200"></a>
<a class="good_name" href="?view=product&goods_id=48">Товар №1</a>
<p class="price">Цена: <span>4890 р.</span></p>
<a href="?view=addtocart&goods_id=48"><img class="addtocart" src="images/addcart.png" alt="Добавить в корзину"></a>
</div>
Если забыть про мои функции, которые я писал выше...
Мне же просто надо выбрать из БД цену товара (по его ID который можно взять из html кода) и занести данные товара (а именно ID товара, его цену и количество = 1) в массив $_SESSION['cart']. И вывести клиенту "В вашей корзине Х товаров на сумму N рублей". При повторном нажатии "Добавить в корзину" проверить если такой ID есть в корзине просто увеличить его количество на единицу.
У меня "затык" получается в том что я не понимаю как AJAXом отправить данные на сервер и получить от него ответ....
|
|

18.10.2017, 22:00
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Упрощенно (на более полное нет времени). Сохранить под любым именем и запустить.
<?php
session_start();
//типа имитации БД
$base = [
11 => ['name' => 'Товар №1', 'price' => 100],
21 => ['name' => 'Товар №2', 'price' => 200],
31 => ['name' => 'Товар №3', 'price' => 300]
];
//корзина
$cart = &$_SESSION['basket'];
//это очень упрощенно, а в реальности должо быть серьезнее
if($_POST['add']) {
//есть ли товар в корзине?
if(!array_key_exists($_POST['add'], $cart)) {
//типа запроса к БД
//в реальности же сложнее
//1) использовать нужно либо mysqli, либо PDO, оригинальное расширение MySQL лучше забыть сразу
//2) выше указанные расширения могут фильтровать данные извне, в случае оригинального расширения этому нужно уделять особенное внимание
$cart[$_POST['add']] = ['count' => 1, 'price' => $base[$_POST['add']]['price' ], 'prop' => ['name' => $base[$_POST['add']]['name' ]]];
} else $cart[$_POST['add']]['count']++; //товар есть в корзине, добавляем еще один
//ответ в формате JSON
header('Content-Type: application/json');
exit(json_encode([
'cart' => //состояние корзины
[
'count' => array_sum(array_map('current', $cart)), //товаров в корзине
'total' => array_sum(array_map('array_product', $cart))], //на сумму
'current' => $cart[$_POST['add']]['count'] //количество добавляемого товара в корзине
])
);
}
?>
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Корзина</title>
<style>
li {
list-style: none;
}
</style>
</head>
<body>
<ul>
<li>Корзина</li>
<li>Товаров: <span id="count">0</span> шт.</li>
<li>На сумму: <span id="total">0</span> руб.</li>
</ul>
<div class="goods">
<a href="?view=product&goods_id=11"><img src="baseimg/11.jpg" alt="Картинка товара" width="200" height="200"></a>
<a class="good_name" href="?view=product&goods_id=11">Товар №1</a>
<p class="price">Цена: <span>1000 р.</span></p>
<button data-add="11">Добавить в корзину</button> <span></span>
</div>
<div class="goods">
<a href="?view=product&goods_id=21"><img src="baseimg/21.jpg" alt="Картинка товара" width="200" height="200"></a>
<a class="good_name" href="?view=product&goods_id=21">Товар №2</a>
<p class="price">Цена: <span>200 р.</span></p>
<button data-add="21">Добавить в корзину</button> <span></span>
</div>
<div class="goods">
<a href="?view=product&goods_id=31"><img src="baseimg/31.jpg" alt="Картинка товара" width="200" height="200"></a>
<a class="good_name" href="?view=product&goods_id=31">Товар №3</a>
<p class="price">Цена: <span>300 р.</span></p>
<button data-add="31">Добавить в корзину</button> <span></span>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
$('button').click(function() {
var btn = $('button').prop('disabled', true), //сделать кнопки добавления товара на время запроса недоступными
bt = $(this); //текущая кнопка
$.post(location, {add: bt.data('add')}, function(data) {
btn.prop('disabled', false); //разрешить добавление товаров
//получен ответ
if(data.cart) {
$.each(data.cart, function(k, v) {
$('#'+k).text(v) //вывести информацию о корзине
});
bt.next().text('В корзине: ' + data.current) //количество текущего товара в корзине
}
})
});
</script>
</body>
</html>
Последний раз редактировалось laimas, 18.10.2017 в 22:07.
|
|

19.10.2017, 09:51
|
Профессор
|
|
Регистрация: 04.12.2012
Сообщений: 3,831
|
|
Стоит добавить проверку на корректность переданного id продукта и на наличие этого продукта в условной бд.
//После строки 14
if(!is_numeric($_POST['add']) or !isset($base[$_POST['add']]))
exit(json_encode(['error'=>'Bad request']));
|
|

19.10.2017, 10:27
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Nexus,
Зачем? В реалии это будет запрос к базе, а в таком случае проще поступить так:
if($id = (int)$_POST['add']) {
//запрос БД, и если вернет, товар есть, иначе лажа
} //иначе лажа
|
|
|
|